<?php
/**
 * DVelum project http://code.google.com/p/phpveil/ , http://dvelum.net
 * Copyright (C) 2011  Kirill A Egorov kirill.a.egorov@gmail.com
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Image Resizer Component
 * @package Image
 * @author Kirill A Egorov kirill.a.egorov@gmail.com
 */
class Image_Resize
{
    /**
     * Crope image
     * @param string  $src - source image path
     * @param string $dest - destination image path
     * @param integer $x - x coord
     * @param integer $y - y coord
     * @param integer $w - width
     * @param integer $h - height
     * @return boolean
     */
    static public function cropImage($src,$dest, $x,$y,$w,$h){
         $imgInfo = getimagesize($src);       
         $img = self::createImg($src, $imgInfo[2]);
         $destImg =  imagecreatetruecolor($w, $h);
         imagecopyresampled($destImg, $img, 0, 0, $x, $y, $w, $h, $w, $h);     
         imagedestroy($img);
         self::saveImage($destImg, $dest, $imgInfo[2]);
         return true;
    }  
    /**
     * Experimental function. Can return wrong result
     * @param resource $img
     * @param array $imgInfo
     * @param integer $newWidth
     * @param integer $newHeight
     */
    static public function cropToSize($img , &$imgInfo , $newWidth , $newHeight )
    {   	
        $width = $imgInfo[0];
        $height= $imgInfo[1];
        
        $newProportion = $newWidth/$newHeight;
        $curProportion = $width / $height;
         
        /*
         * Resize the image if one of the sides is lesser than expected
         */
        if($newHeight>$height || $newWidth > $width)
        {      	
        	if($newHeight>$height){        	
	        	$step = $newHeight - $height;
	        	$width+=$step*$curProportion;
	        	$height+=$step;     	
	        }else{
	        	$step = $newWidth - $width;
	        	$width+=$step;
	        	$height+=$step*$curProportion;   	        	
	        }    
	        
	        $dest = self::createDupliateLayer($imgInfo[2], $width, $height);  	
	        imagecopyresampled($dest, $img, 0, 0, 0, 0, $width, $height, $imgInfo[0], $imgInfo[1]);
	        $imgInfo[0] = $width;
	        $imgInfo[1] = $height;
	        imagedestroy($img);
	        $img = $dest;
        }

        $curProportion = $width / $height;
         
         if($width > $height){            
            if($newWidth >= $newHeight){                    
                if($curProportion > $newProportion){           
                    $nWidth = $width;
                	$nHeight = $newHeight * $curProportion;             	
                    $x=0;
                    $y=0;
                }else{
                
                    $nHeight = $newHeight;
                    $nWidth = $newWidth / $curProportion; 	
                    $x=0;
                    $y=0;
                }
                 
                $dest =  self::createDupliateLayer($imgInfo[2] , $newWidth, $newHeight);
   
                imagecopyresampled($dest, $img, 0,0,$x,$y, $newWidth, $newHeight, $width, $height);
                imagedestroy($img);
                $imgInfo[0] = $newWidth;
                $imgInfo[1] = $newHeight;
                return $dest;
            } else{
                
                $nWidth = $height * $newProportion;
            	$nHeight = $height;
            	
                $x=intval(($width-$newWidth )/4);
                $y=0;
            }       
         } else{
         	        
            if($newWidth<= $newHeight){              
                
              if($curProportion > $newProportion){
                
                    $nHeight = $height;
                    $nWidth = $width*$curProportion;
                    $x=intval(($width-$nWidth )/2);
                    $y=0;
                }else{
                    $nWidth = $width;
                    $nHeight = $width/$newProportion;                	
                    $x=0;
                    $y=intval(($height-$newHeight )/4);               
                }
            } else{  
                 if($curProportion > $newProportion){               
                    $nWidth = $width;
                	$nHeight = $newHeight * $curProportion;               	
                    $x=0;
                    $y=0;   
                }else{
                    $nWidth = $width;
                    $nHeight = $width/$newProportion;             	
                    $x=0;
                    $y=intval(($height-$newHeight )/4);                 
                }  
            } 
         }

        $dest =  self::createDupliateLayer($imgInfo[2] , $newWidth, $newHeight);
   
        imagecopyresampled($dest, $img, 0,0,$x,$y, $newWidth, $newHeight, $nWidth, $nHeight);
        imagedestroy($img);

        $imgInfo[0] = $newWidth;
        $imgInfo[1] = $newHeight;
        
        return $dest;
    }
    /**
     * Create image from file
     * @param string $path - file path
     * @param integer $type - image type constant, source file type
     */
    static public function createImg($path , $type){
    	switch ($type) {
              case IMAGETYPE_GIF : $im = imagecreatefromgif($path); 
                  break;
              case IMAGETYPE_JPEG: $im = imagecreatefromjpeg($path);  
                  break;
              case IMAGETYPE_PNG: $im = imagecreatefrompng($path); 
                  break;
              default:  trigger_error('Unsupported filetype!', E_USER_WARNING); 
                              return false;
                   break;
         }
         return $im;
    }
    
    /**
     * Resize image
     * @param string $imgPath
     * @param integer $width
     * @param integer $height
     * @param string $newImgPath
     */
    static public function resize($imgPath , $width , $height , $newImgPath, $fit = false , $crop = true)
    {
         /*
          * Check if GD extension is loaded
          */
         if (!extension_loaded('gd') && !extension_loaded('gd2')) {
             trigger_error("GD is not loaded", E_USER_WARNING);
             return false;
         }     
         /*
          * Get Image size info
          */
         $imgInfo = getimagesize($imgPath);
         $im = self::createImg($imgPath, $imgInfo[2]);             
         /*
          * If image sizes less then need just save image into the new location
          */
         if($imgInfo[0]< $width && $imgInfo[1]<$height){
              self::saveImage($im, $newImgPath, $imgInfo[2]);
              return true;
         }        
         /*
          *  Crope mode
          */
         if($crop){
         	$im = self::cropToSize($im, $imgInfo , $width, $height);
         	self::saveImage($im, $newImgPath, $imgInfo[2]);
         	return true;
         }	
         /*
          * Resize it, but keep it proportional
          */
         if ($width/$imgInfo[0] > $height/$imgInfo[1]) {
              $nWidth = $width;
              $nHeight = $imgInfo[1]*($width/$imgInfo[0]);
         }else{
              $nWidth = $imgInfo[0]*($height/$imgInfo[1]);
              $nHeight = $height;
         }
          
         $nWidth = round($nWidth);
         $nHeight = round($nHeight);
           
         if($fit){
              
            if($nWidth > $width){
                  $k = $width / $nWidth;
                  $nWidth = $width;
                  $nHeight = $nHeight* $k;
            }
                      
            if($nHeight>$height){                      
                $k = $height / $nHeight;
                $nHeight = $height;
                $nWidth = $nWidth* $k;
            }        
            $nWidth = round($nWidth);
            $nHeight = round($nHeight);
         }
                
         $newImg = self::createDupliateLayer($imgInfo[2], $nWidth, $nHeight);     
         
         imagecopyresampled($newImg, $im, 0, 0, 0, 0, $nWidth, $nHeight, $imgInfo[0], $imgInfo[1]);
         imagedestroy($im);
         
         self::saveImage($newImg, $newImgPath, $imgInfo[2]);
         return true;
    }
    /**
     * Create image resource for manipulation, 
     * transparent for IMG_GIF and IMG_PNG
     * @param constant $type image type
     * @param integer $width
     * @param integer $height
     * @return resorce $image
     */
    static protected function createDupliateLayer($type , $width , $height){
        $img = imagecreatetruecolor($width, $height);
        if($type == IMG_GIF || $type == IMG_PNG){
              imagealphablending($img, false);
              imagesavealpha($img,true);
              $transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
              imagefilledrectangle($img, 0, 0, $width, $height, $transparent);
        }
        return $img;
    }
    /**
     * Save image to file
     * @param resource $resource - image resource
     * @param string $path - path to file
     * @param int $imgInfo - image type constant
     */
    static protected function saveImage($resource, $path , $imgType){
         switch ($imgType) {
              case IMAGETYPE_GIF: imagegif($resource,$path);
                   break;
              case IMAGETYPE_JPEG: imagejpeg($resource,$path , 100); 
                   break;
              case IMAGETYPE_PNG: imagepng($resource,$path); 
                  break;
              default: return false;    
         }
         imagedestroy($resource);
    }
}